package com.achobeta.recruitment.service.impl.interact;

import com.achobeta.recruitment.common.ResultCode;
import com.achobeta.recruitment.component.ModelMessageSender;
import com.achobeta.recruitment.component.MyThreadPool;
import com.achobeta.recruitment.config.AppConfig;
import com.achobeta.recruitment.dao.interact.MessageMapper;
import com.achobeta.recruitment.model.*;
import com.achobeta.recruitment.model.vo.MessageVO;
import com.achobeta.recruitment.service.interact.MessageService;
import com.achobeta.recruitment.service.manager.ManagerService;
import com.achobeta.recruitment.service.student.StudentInfoService;
import com.achobeta.recruitment.service.student.StudentService;
import com.achobeta.recruitment.service.wx.WxUserService;
import com.achobeta.recruitment.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.concurrent.FutureTask;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 马拉圈
 * Date: 2023-10-31
 * Time: 17:57
 */
@Slf4j
@Service
public class MessageServiceImpl implements MessageService {


    @Value("${redirect.domain}")
    private String redirectDomain;

    @Value("${redirect.fe}")
    private String redirectFE;

    @Value("${recruit.result.url}")
    private String resultUrl;

    @Value("${recruit.choose.url}")
    private String chooseUrl;


    @Autowired
    private MessageMapper messageMapper;

    @Autowired
    private WxUserService wxUserService;

    @Autowired
    private StudentInfoService studentInfoService;

    @Autowired
    private ManagerService managerService;

    @Autowired
    private StudentService studentService;

    @Autowired
    private ModelMessageSender modelMessageSender;


    @Override
    public void loadImage(MultipartFile file, String path) {
        CheckUtils.checkNULL(file, path);
        // 下载
        MediaUtils.loadFile(file, AppConfig.ROOT + path);
        log.info(ResultCode.SUCCESS + "保存成功：" + redirectDomain + "/" + path);
    }

    public String sendModelMessage(Message message) {
        String openid = message.getOpenid();
        WxUser wxUser = wxUserService.selectWxUserByOpenid(openid);
        // 校验
        CheckUtils.checkNULL(wxUser);
        // 发送请求
        return modelMessageSender.sendModelMessage(message);
    }


    @Override
    public void sendMessageNormal(Message message) {
        // 校验
        CheckUtils.checkStringParams(ResultCode.FAILED_PARAMS_VALIDATE,
                message.getOpenid(), message.getContent(), message.getTitle());
        if(studentService.selectStudentByOpenid(message.getOpenid()) == null) {
            CheckUtils.printWarn(ResultCode.FAILED_USER_NOT_EXISTS);
            return;
        }
        CheckUtils.checkNULL(message.getNormal());
        message.setDeadline(null);
        message.setTicket(null);
        // 插入表
        int rows = messageMapper.insertSelective(message);
        // 校验
        CheckUtils.checkRows(rows, 1, ResultCode.FAILED_CREATE);
        // 插入成功发送模板消息
        message.setUrl(redirectFE + resultUrl + "?messageId=" + message.getId());
//        MessageUtils.cutMessage(message);
        String result = sendModelMessage(message);
        // 校验
        CheckUtils.checkResult(result, ResultCode.FAILED);
        // 成功
        log.info(ResultCode.SUCCESS + "  message id: " + message.getId());
    }

    @Override
    public void sendMessageLimit(Message message) {
        // 校验
        CheckUtils.checkStringParams(ResultCode.FAILED_PARAMS_VALIDATE,
                message.getOpenid(), message.getContent(), message.getTitle());
        if(studentService.selectStudentByOpenid(message.getOpenid()) == null) {
            CheckUtils.printWarn(ResultCode.FAILED_USER_NOT_EXISTS);
            return;
        }
        Byte deadline = message.getDeadline();
        CheckUtils.checkNULL(deadline);
        message.setTicket(null);
        message.setNormal(null);
        // 插入表
        int rows = messageMapper.insertSelective(message);
        // 校验
        CheckUtils.checkRows(rows, 1, ResultCode.FAILED_CREATE);
        // 插入成功发送模板消息
        if(deadline > 0) { //小于等于0，则没有失效的时候
            Timer timer = new Timer();
            log.info("计时开始, 于" + deadline + "h后截止");
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    updateState(message.getId(), (byte) 3);
                    log.info(message.getId() + " 此消息已失效");
                }
            }, deadline * 3600 * 1000);
        }
        message.setUrl(redirectFE + chooseUrl + "?messageId=" + message.getId());
//        MessageUtils.cutMessage(message);
        String result = sendModelMessage(message);
        // 校验
        CheckUtils.checkResult(result, ResultCode.FAILED);
        // 成功
        log.info(ResultCode.SUCCESS + "  message id: " + message.getId());
    }

    @Override
    public void sendMessageURL(Message message) {
        // 校验
        CheckUtils.checkStringParams(ResultCode.FAILED_PARAMS_VALIDATE,
                message.getOpenid(), message.getContent(), message.getTitle());
        if(studentService.selectStudentByOpenid(message.getOpenid()) == null) {
            CheckUtils.printWarn(ResultCode.FAILED_USER_NOT_EXISTS);
            return;
        }
        CheckUtils.checkNULL(message.getUrl());
        message.setNormal(null);
        message.setDeadline(null);
        message.setTicket(null);
        // 插入表
        int rows = messageMapper.insertSelective(message);
        // 校验
        CheckUtils.checkRows(rows, 1, ResultCode.FAILED_CREATE);
        // 插入成功发送模板消息
//        MessageUtils.cutMessage(message);
        String result = sendModelMessage(message);
        // 校验
        CheckUtils.checkResult(result, ResultCode.FAILED);
        // 成功
        log.info(ResultCode.SUCCESS + "  message id: " + message.getId());
    }

    @Override
    public void sendMessageWithPhoto(Message message) {
        // 校验
        CheckUtils.checkStringParams(ResultCode.FAILED_PARAMS_VALIDATE,
                message.getOpenid(), message.getContent(), message.getTitle(), message.getTicket());
        if(studentService.selectStudentByOpenid(message.getOpenid()) == null) {
            CheckUtils.printWarn(ResultCode.FAILED_USER_NOT_EXISTS);
            return;
        }
        message.setNormal(null);
        message.setDeadline(null);
        // 插入表
        int rows = messageMapper.insertSelective(message);
        // 校验
        CheckUtils.checkRows(rows, 1, ResultCode.FAILED_CREATE);
        // 插入成功发送模板消息
        message.setUrl(redirectFE + resultUrl + "?messageId=" + message.getId());
//        MessageUtils.cutMessage(message);
        String result = sendModelMessage(message);
        // 校验
        CheckUtils.checkResult(result, ResultCode.FAILED);
        // 成功
        log.info(ResultCode.SUCCESS + "  message id: " + message.getId());
    }

    @Override
    public void updateState(Integer messageId, Byte state) {
        // 校验
        CheckUtils.checkNULL(messageId, state);
        // 查询message
        Message message = selectMessageById(messageId);
        if(message == null || message.getDeleteState() != 0) {
            CheckUtils.printWarn(ResultCode.FAILED_MESSAGE_IS_EXISTS);
        }
        // 如果不是1的话，就没有必要修改
        if(message.getState() != 1 || (state != 2 && state != 3)) {
//           CheckUtils.printWarn(ResultCode.FAILED_MESSAGE_STATE_UPDATE);
            log.warn(ResultCode.FAILED_MESSAGE_STATE_UPDATE.toString());
            return;
        }
        // 构造修改对象
        Message updateMessage = new Message();
        updateMessage.setId(messageId);
        updateMessage.setState(state);
        updateMessage.setUpdateTime(new Date());
        // 调用dao层进行修改
        int rows = messageMapper.updateByPrimaryKeySelective(updateMessage);
        // 校验
        CheckUtils.checkRows(rows, 1, ResultCode.FAILED_MESSAGE_STATE_UPDATE);
        // 成功
        log.info(ResultCode.SUCCESS + " message id：" + messageId + " 状态成功转化为：" + state);
    }

    @Override
    public Message selectMessageById(Integer messageId) {
        // 校验
        CheckUtils.checkNULL(messageId);
        // 查询
        Message message = messageMapper.selectByPrimaryKey(messageId);
        // 无论如何都返回
        return message;
    }

    @Override
    public MessageVO getDetail(Integer messageId, String openid) {
        // 校验
        CheckUtils.checkStringParams(ResultCode.FAILED_PARAMS_OPENID, openid);
        CheckUtils.checkNULL(messageId);
        // 查询消息
        Message message = selectMessageById(messageId);
        // 校验
        CheckUtils.checkNULL(message);
        // 获取openid与managerId
        if(!openid.equals(message.getOpenid())) {
           CheckUtils.printWarn(ResultCode.FAILED_UNAUTHORIZED);//没有权限看到详情
        }
        Integer managerId = message.getManagerId();
        // 多表查询(线程池执行任务期间出现异常会被try catch，并抛出个新异常)
        FutureTask<StudentInfo> task1 = new FutureTask<>(() -> {
            return studentInfoService.selectStudentInfoByOpenId(openid, (byte) 1);
//            return studentInfoService.selectStudentInfoByOpenId("666");
        });
        FutureTask<Manager> task2 = new FutureTask<>(() -> {
            return managerService.selectManagerById(managerId);
        });
        // 让线程池执行
        Map<String, Object> result = MyThreadPool.submit(task1, task2);
        // 校验
        StudentInfo studentInfo = (StudentInfo) result.get("task1");
        Manager manager = (Manager) result.get("task2");
        CheckUtils.checkNULL(studentInfo, manager);
        // 构造VO对象
        MessageVO messageVO = BeanCopyUtils.copyBean(message, MessageVO.class);
        messageVO.setName(studentInfo.getName());
        messageVO.setManagerName(manager.getManagerName());
        // 成功返回
        log.info(ResultCode.SUCCESS + " 查询详情 消息 id：" + messageId);
        return messageVO;
    }

    @Override
    public void sendMessageNormal(List<Student> students, Message message) {
        CheckUtils.checkNULL(students);
        for(Student student : students) {
            CheckUtils.checkNULL(student);
            if(studentService.selectStudentByOpenid(student.getOpenid()) == null) {
                continue;
            }
            message.setId(null);
            message.setOpenid(student.getOpenid());
            sendMessageNormal(message);
        }
    }

    @Override
    public void sendMessageLimit(List<Student> students, Message message) {
        CheckUtils.checkNULL(students);
        for(Student student : students) {
            CheckUtils.checkNULL(student);
            if(studentService.selectStudentByOpenid(student.getOpenid()) == null) {
                continue;
            }
            message.setId(null);
            message.setOpenid(student.getOpenid());
            sendMessageLimit(message);
        }
    }

    @Override
    public void sendMessageURL(List<Student> students, Message message) {
        CheckUtils.checkNULL(students);
        for(Student student : students) {
            CheckUtils.checkNULL(student);
            if(studentService.selectStudentByOpenid(student.getOpenid()) == null) {
                continue;
            }
            message.setId(null);
            message.setOpenid(student.getOpenid());
            sendMessageURL(message);
        }
    }

    @Override
    public void sendMessageWithPhoto(List<Student> students, Message message) {
        CheckUtils.checkNULL(students);
        for(Student student : students) {
            CheckUtils.checkNULL(student);
            if(studentService.selectStudentByOpenid(student.getOpenid()) == null) {
                continue;
            }
            message.setId(null);
            message.setOpenid(student.getOpenid());
            sendMessageWithPhoto(message);
        }
    }

    @Override
    public List<MessageVO> selectMessageByOpenId(String openid) {
        // 校验
        CheckUtils.checkStringParams(ResultCode.FAILED_PARAMS_OPENID, openid);
        // 查询此用户是否存在
        WxUser wxUser = wxUserService.selectWxUserByOpenid(openid);
        CheckUtils.checkNULL(wxUser);
        // 查询消息列表
        List<MessageVO> messageVOS = messageMapper.selectMessageByOpenId(openid);
        messageVOS = messageVOS == null ? new ArrayList<>() : messageVOS;
        // 无论如何都返回，空集合也正常
        log.info(ResultCode.SUCCESS + " 查询到的行数：" + messageVOS.size());
        return messageVOS;
    }
}
